/**
 * 身份证验证Util
 */
export class CreditUtil {

    /**
     * 校验身份证号码
     */
    static isIDCardValid(value) {
        if (!CreditUtil.checkIdCardDate(value)) return false;
        return (value.length === 18 && CreditUtil.isIDCard18(value));
    }

    /**
     * 校验18位身份证号码
     */
    static isIDCard18(value) {
        if (value === null || typeof value === 'undefined' || value.length !== 18) return false;
        if (!value.match("[\\d]+[X]?")) return false;

        let code = "10X98765432";
        let weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1];

        let nSum = 0;
        for (let i = 0; i < 17; ++i) {
            nSum += parseInt(value.charAt(i) - '0') * weight[i];
        }

        let nCheckNum = nSum % 11;
        let chrValue = value.charAt(17);
        let chrCode = code.charAt(nCheckNum);
        if (chrValue === chrCode) return true;
        if (nCheckNum === 2 && (chrValue + ('a' - 'A') === chrCode)) return true;
        return false;
    }


    /**
     * 校验身份证的日期格式是否正确
     */
    static checkIdCardDate(value) {
        if (value === null || typeof value === 'undefined' || !value.match("[\\d]+[X]?")) {
            return false;
        }

        let nLen = value.length;
        if (nLen !== 15 && nLen !== 18) return false;

        let date = null;
        if (nLen === 15) {
            date = "19" + value.substring(6, 12);
        }
        else {
            date = value.substring(6, 14);
        }
        return CreditUtil.checkDate8(date);
    }

    /**
     * 校验8位日期
     */
    static checkDate8(date) {
        if (date.length !== 8) return false;
        try {
            let year = parseInt(date.substring(0, 4));
            let month = parseInt(date.substring(4, 6));
            let day = parseInt(date.substring(6, 8));
            return CreditUtil.checkDate(year, month, day);
        }
        catch (e) {
        }
        return false;
    }

    static checkDate(nYear, nMonth, nDay) {
        if (nYear < 1800 || nMonth < 1 || nMonth > 12 || nDay < 1 || nDay > 31)
            return false;

        if (nMonth === 2) {
            if (nDay > 29) return false;
            if (nDay === 29 && !((nYear % 4 === 0 && nYear % 100 !== 0) || nYear % 400 === 0))
                return false;
            return true;
        }

        if (nMonth === 4 || nMonth === 6 || nMonth === 9 || nMonth === 11) {
            if (nDay < 31) return true;
            else return false;
        }
        return true;
    }

}
